<!DOCTYPE html>
<html>
<head>
    <title>Frequency Spectrum</title>
</head>
<body>
    <canvas id="physicsCanvas" width="600" height="450"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // Style settings
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        ctx.font = '18px sans-serif';

        // Coordinates and scaling
        const yAxisX = 100;
        const xAxisY = 380;
        const plotTopY = 50;
        const plotRightX = 550;

        const freqToX = (f) => {
            // Map frequency range [290, 310] to pixel range [150, 500]
            const f_min = 290;
            const f_max = 310;
            const x_min = 172;
            const x_max = 488;
            return x_min + ((f - f_min) / (f_max - f_min)) * (x_max - x_min);
        };

        const x_292 = freqToX(292);
        const x_300 = freqToX(300);
        const x_308 = freqToX(308);

        // --- Draw Axes ---
        ctx.beginPath();
        // Y-axis
        ctx.moveTo(yAxisX, xAxisY);
        ctx.lineTo(yAxisX, plotTopY);
        // Y-axis arrowhead
        ctx.moveTo(yAxisX - 5, plotTopY + 10);
        ctx.lineTo(yAxisX, plotTopY);
        ctx.lineTo(yAxisX + 5, plotTopY + 10);
        // X-axis
        ctx.moveTo(yAxisX, xAxisY);
        ctx.lineTo(plotRightX, xAxisY);
        ctx.stroke();

        // --- Draw Labels and Ticks ---
        ctx.textAlign = 'left';
        ctx.textBaseline = 'middle';
        ctx.fillText('amplitude', 10, 180);

        ctx.textAlign = 'center';
        ctx.textBaseline = 'top';
        ctx.fillText('f / kHz', 500, xAxisY + 20);

        // Origin label
        ctx.textAlign = 'right';
        ctx.textBaseline = 'middle';
        ctx.fillText('0', yAxisX - 10, xAxisY);

        // X-axis ticks and labels
        ctx.textAlign = 'center';
        ctx.textBaseline = 'top';
        
        // Tick for 292
        ctx.beginPath();
        ctx.moveTo(x_292, xAxisY);
        ctx.lineTo(x_292, xAxisY + 5);
        ctx.stroke();
        ctx.fillText('292', x_292, xAxisY + 10);

        // Tick for 300
        ctx.beginPath();
        ctx.moveTo(x_300, xAxisY);
        ctx.lineTo(x_300, xAxisY + 5);
        ctx.stroke();
        ctx.fillText('300', x_300, xAxisY + 10);

        // Tick for 308
        ctx.beginPath();
        ctx.moveTo(x_308, xAxisY);
        ctx.lineTo(x_308, xAxisY + 5);
        ctx.stroke();
        ctx.fillText('308', x_308, xAxisY + 10);

        // --- Draw Spectrum ---
        // Carrier wave spike
        ctx.beginPath();
        ctx.moveTo(x_300, xAxisY);
        ctx.lineTo(x_300, plotTopY + 20);
        ctx.stroke();

        // Sidebands
        const sidebandMaxHeight = 60;
        
        // Lower sideband (292 to 300)
        ctx.beginPath();
        ctx.moveTo(x_292, xAxisY);
        const cp1x_l = x_292 + (x_300 - x_292) * 0.2;
        const cp1y_l = xAxisY - sidebandMaxHeight * 0.7;
        const cp2x_l = x_292 + (x_300 - x_292) * 0.4;
        const cp2y_l = xAxisY - sidebandMaxHeight * 0.9;
        const midx_l = x_292 + (x_300 - x_292) * 0.55;
        const midy_l = xAxisY - sidebandMaxHeight * 0.5;
        ctx.bezierCurveTo(cp1x_l, cp1y_l, cp2x_l, cp2y_l, midx_l, midy_l);
        
        const cp3x_l = x_300 - (x_300 - x_292) * 0.3;
        const cp3y_l = xAxisY - sidebandMaxHeight * 0.1;
        const cp4x_l = x_300 - (x_300 - x_292) * 0.25;
        const cp4y_l = xAxisY - sidebandMaxHeight * 0.8;
        ctx.bezierCurveTo(cp3x_l, cp3y_l, cp4x_l, cp4y_l, x_300, xAxisY);
        ctx.stroke();
        
        // Upper sideband (300 to 308)
        ctx.beginPath();
        ctx.moveTo(x_300, xAxisY);
        const cp1x_u = x_300 + (x_308 - x_300) * 0.3;
        const cp1y_u = xAxisY - sidebandMaxHeight * 0.85;
        const cp2x_u = x_300 + (x_308 - x_300) * 0.4;
        const cp2y_u = xAxisY - sidebandMaxHeight * 0.2;
        const midx_u = x_300 + (x_308 - x_300) * 0.55;
        const midy_u = xAxisY - sidebandMaxHeight * 0.5;
        ctx.bezierCurveTo(cp1x_u, cp1y_u, cp2x_u, cp2y_u, midx_u, midy_u);

        const cp3x_u = x_308 - (x_308 - x_300) * 0.3;
        const cp3y_u = xAxisY - sidebandMaxHeight * 0.9;
        const cp4x_u = x_308 - (x_308 - x_300) * 0.15;
        const cp4y_u = xAxisY - sidebandMaxHeight * 0.4;
        ctx.bezierCurveTo(cp3x_u, cp3y_u, cp4x_u, cp4y_u, x_308, xAxisY);
        ctx.stroke();

        // --- Draw Caption ---
        ctx.font = 'bold 18px sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
        ctx.fillText('Fig. 5.1', canvas.width / 2, canvas.height - 5);

    </script>
</body>
</html>